//
//  KNNetworkingManager.m
//  Backhome
//
//  Created by kwep_vbn on 2017/3/22.
//  Copyright © 2017年 SmartHome. All rights reserved.
//

#import "KNNetworkingManager.h"
#import "AFNetworking.h"

@interface KNNetworkingManager ()

@property (copy, nonatomic) NSString *baseUrl;

@property (assign, nonatomic) KNResponseSerializer responseSerializer;

@property (assign, nonatomic) KNRequestSerializer requestSerializer;

@property (strong, nonatomic) NSMutableDictionary *commonHeaders;

@property (assign, nonatomic) NSInteger timeout;


@end

@implementation KNNetworkingManager

#pragma mark - 初始化
+ (instancetype)shareInstance {
    static KNNetworkingManager *manager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[KNNetworkingManager alloc] init];
    });
    return manager;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        self.baseUrl = nil;
        self.requestSerializer = KNRequestSerializerJSON;
        self.responseSerializer = KNRequestSerializerJSON;
        self.commonHeaders = @{}.mutableCopy;
        self.timeout = 60;
        self.allTasks = @[].mutableCopy;
    }
    return self;
}

#pragma mark - getter && setter

+ (void)setBaseUrl:(NSString *)baseUrl {
    [KNNetworkingManager shareInstance].baseUrl = baseUrl;
}

+ (NSString *)baseUrl {
    return [KNNetworkingManager shareInstance].baseUrl;
}

+ (void)setResponseSerializer:(KNResponseSerializer)responseSerializer {
    [KNNetworkingManager shareInstance].responseSerializer = responseSerializer;
}

+ (KNResponseSerializer)responseSerializer {
    return [KNNetworkingManager shareInstance].responseSerializer;
}

+ (void)setRequestSerializer:(KNRequestSerializer)requestSerializer {
    [KNNetworkingManager shareInstance].requestSerializer = requestSerializer;
}

+ (KNRequestSerializer)requestSerializer {
    return [KNNetworkingManager shareInstance].requestSerializer;
}

+ (void)setCommonHeaders:(NSMutableDictionary *)headers {
    [KNNetworkingManager shareInstance].commonHeaders = headers;
}

+ (NSMutableDictionary *)commonHeaders {
    return [KNNetworkingManager shareInstance].commonHeaders;
}

+ (void)setTimeout:(NSInteger)timeout {
    [KNNetworkingManager shareInstance].timeout = timeout;
}

+ (NSInteger)timeOut {
    return [KNNetworkingManager shareInstance].timeout;
}

#pragma mark - 配置网络请求
+ (AFHTTPSessionManager *)manager {
    dispatch_async(dispatch_get_main_queue(), ^{
        [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    });
    
    AFHTTPSessionManager *manager = nil;;
    if ([self baseUrl] != nil) {
        manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:[self baseUrl]]];
    } else {
        manager = [AFHTTPSessionManager manager];
    }
    manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
    
    switch ([self requestSerializer]) {
        case KNRequestSerializerJSON: {
            manager.requestSerializer = [AFJSONRequestSerializer serializer];
            break;
        }
        case KNRequestSerializerPlainText: {
            manager.requestSerializer = [AFHTTPRequestSerializer serializer];
            break;
        }
        default: {
            break;
        }
    }
    
    switch ([self responseSerializer]) {
        case KNResponseSerializerJSON: {
            manager.responseSerializer = [AFJSONResponseSerializer serializer];
            break;
        }
        case KNResponseSerializerXML: {
            manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
            break;
        }
        case KNResponseSerializerData: {
            manager.responseSerializer = [AFHTTPResponseSerializer serializer];
            break;
        }
        default: {
            break;
        }
    }
    
    manager.requestSerializer.stringEncoding = NSUTF8StringEncoding;
    
    NSMutableDictionary *headers = [KNNetworkingManager shareInstance].commonHeaders;
    
    for (NSString *key in headers.allKeys) {
        [manager.requestSerializer setValue:headers[key] forHTTPHeaderField:key];
    }
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithArray:@[@"application/json",
                                                                              @"application/octet-stream",
                                                                              @"text/html",
                                                                              @"image/jpeg",
                                                                              @"text/json",
                                                                              @"text/plain",
                                                                              @"text/javascript",
                                                                              @"text/xml",
                                                                              @"image/*"]];
    
    manager.requestSerializer.timeoutInterval = [KNNetworkingManager shareInstance].timeout;
    
    // 设置允许同时最大并发数量，过大容易出问题
    manager.operationQueue.maxConcurrentOperationCount = 3;
    return manager;
}

#pragma mark - 请求

#pragma mark - GET
+ (NSURLSessionDataTask *)GET:(NSString *)URLString
                   parameters:(nullable id)parameters
                     progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
                      success:(KNNetworkingSuccess)success
                      failure:(KNNetworkingError)failure {
    
    AFHTTPSessionManager *manager = [self manager];
    NSURLSessionDataTask *task = [manager GET:URLString parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
//        NSLog(@"%d/%d", downloadProgress.completedUnitCount, downloadProgress.totalUnitCount);
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        [[KNNetworkingManager shareInstance].allTasks removeObject:task];
        NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
        success?success(responseObject,response):nil;
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [[KNNetworkingManager shareInstance].allTasks removeObject:task];
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
        failure?failure(error,response):nil;
    }];
    if (task) {
        [[KNNetworkingManager shareInstance].allTasks addObject:task];
    }
    return task;
}

#pragma mark - POST
+ (NSURLSessionDataTask *)POST:(NSString *)URLString
                    parameters:(nullable id)parameters
                      progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
                       success:(KNNetworkingSuccess)success
                       failure:(KNNetworkingError)failure {
    
    AFHTTPSessionManager *manager = [self manager];
    NSURLSessionDataTask *task = [manager POST:URLString parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
//        NSLog(@"%d/%d", downloadProgress.completedUnitCount, downloadProgress.totalUnitCount);
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        [[KNNetworkingManager shareInstance].allTasks removeObject:task];
        NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
        success?success(responseObject,response):nil;
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [[KNNetworkingManager shareInstance].allTasks removeObject:task];
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
        failure?failure(error,response):nil;
    }];
    if (task) {
        [[KNNetworkingManager shareInstance].allTasks addObject:task];
    }
    return task;
}

+ (NSURLSessionDataTask *)UPLOAD:(NSString *)URLString
                      parameters:(nullable id)parameters
                      uploadFile:(NSData *)data
                  uploadFileName:(NSString *)fileName
                        mimeType:(NSString *)mimeType
                        progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
                         success:(KNNetworkingSuccess)success
                         failure:(KNNetworkingError)failure {
    AFHTTPSessionManager *manager = [self manager];
    NSURLSessionDataTask *task = [manager POST:URLString parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        [formData appendPartWithFileData:data name:@"file" fileName:fileName mimeType:mimeType];
    } progress:^(NSProgress * _Nonnull uploadProgress) {
//        NSLog(@"%d/%d", uploadProgress.completedUnitCount, uploadProgress.totalUnitCount);
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        [[KNNetworkingManager shareInstance].allTasks removeObject:task];
        NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
        success?success(responseObject,response):nil;
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [[KNNetworkingManager shareInstance].allTasks removeObject:task];
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
        failure?failure(error,response):nil;
    }];
    if (task) {
        [[KNNetworkingManager shareInstance].allTasks addObject:task];
    }
    return task;
}

+ (NSURLSessionTask *)downloadFile:(NSString *)urlString
                        progress:(nullable void (^)(NSProgress *downloadProgress))progress
                       destination:(nullable NSURL*(^)(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response))destination
                         success:(KNNetworkingSuccess)success
                         failure:(KNNetworkingError)failure {
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
    NSURL *URL = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:URL];
    NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
        progress?progress(downloadProgress):nil;
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        if (destination == nil) {
            return nil;
        }
        return destination(targetPath, response);
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        if (!error) {
            [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
            [[KNNetworkingManager shareInstance].allTasks removeObject:downloadTask];
            NSHTTPURLResponse *response = (NSHTTPURLResponse *)response;
            success?success(filePath,response):nil;
        } else {
            failure?failure(error,response):nil;
        }
    }];
    if (downloadTask) {
        [[KNNetworkingManager shareInstance].allTasks addObject:downloadTask];
        [downloadTask resume];
    }
    return downloadTask;
}

#pragma mark - 取消
+ (void)cancelTask:(NSURLSessionDataTask *)task {
    [task cancel];
}

+ (void)cacelAllTask {
    [[KNNetworkingManager shareInstance].allTasks performSelector:@selector(cancel) withObject:nil];
}

@end
